package cn.scw.framework.protocol.tcp;

import cn.scw.common.utils.ByteUtil;
import cn.scw.common.utils.spring.SpringUtils;
import cn.scw.framework.protocol.DataResolverManager;
import cn.scw.framework.protocol.ResolverContext;
import cn.scw.framework.protocol.SenderType;
import io.netty.channel.*;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * 处理协议内容
 */
public class ProtoDataHandler extends ChannelInboundHandlerAdapter {

    private static Logger logger= LoggerFactory.getLogger(ProtoDataHandler.class);

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg){

        int responseCode=1;

        try {

            byte[] content= (byte[]) msg;
            TcpServerManager tcpServerManager=TcpServerManager.getManager();
            //获取内容二进制数组

            //查询到该tcp连接的句柄
            ChannelHandle channelHandle=tcpServerManager.getChannelHandleByChannelId(ctx.channel().id().asLongText());
            //如果没找到对应的通道或者通道已关闭，则关闭当前连接
            if(channelHandle==null||channelHandle.getChannel()==null||!channelHandle.getChannel().isActive()){
                ctx.channel().close();
                return;
            }

            InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();

            logger.info(
                    "receiveddata:[host："+inetSocketAddress.getHostString()+
                            ",port:"+inetSocketAddress.getPort()+
                            ",content:"+ ByteUtil.bytesToBinaryString((byte[]) msg)+"]");

            //构造入参上下文
            ResolverContext context = new ResolverContext();
            context.setSenderIp(inetSocketAddress.getAddress());
            context.setSenderType(SenderType.TCP);
            context.setPort(inetSocketAddress.getPort());
            context.setChannelHandle(channelHandle);

            //如果当前通道尚未通过验证
            /*if(!channelHandle.getIsAuthed()){
                //认证 sensorCode 认证的设备编号
                tcpServerManager.authTcpChannel(sensorCode,channelHandle);
            }*/

            //解析数据
            DataResolverManager.getInstance().resolveData(content, context);

        }catch (Exception ex){
            responseCode=0;
            InetSocketAddress inetSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
            logger.error(ex.getMessage()+
                    ",receiveddata:[host："+inetSocketAddress.getHostString()+
                    ",port:"+inetSocketAddress.getPort()+
                    ",content:"+ByteUtil.bytesToBinaryString((byte[]) msg)+"]");
        }finally {
            //释放资源
            ReferenceCountUtil.release(msg);
        }

        try {
            //由于设备目前对报文的读取机制，需要延迟5秒后再发送，才能够更大概率被成功读取
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //发送回复
//        ByteBuf encoded = ctx.channel().alloc().buffer(4);
//        encoded.writeBytes(ByteUtil.intToByteArray(responseCode));
////        encoded.writeBytes("001".getBytes());
//        ctx.channel().writeAndFlush(encoded);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        logger.info("断开了,移除通道"+ctx.channel());
        //从管理器中释放通道资源
        SpringUtils.getBean(TcpServerManager.class).unRegistTcpChannel(ctx.channel());
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelRegistered()} to forward
     * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
     *
     * Sub-classes may override this method to change behavior.
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelRegistered();
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelUnregistered()} to forward
     * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
     *
     * Sub-classes may override this method to change behavior.
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelUnregistered();
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelReadComplete()} to forward
     * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
     *
     * Sub-classes may override this method to change behavior.
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelReadComplete();
    }

    /**
     * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward
     * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
     *
     * Sub-classes may override this method to change behavior.
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        ctx.fireExceptionCaught(cause);
        logger.warn(cause.getMessage());
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelActive()} to forward
     * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
     *
     * Sub-classes may override this method to change behavior.
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelActive();

        //向管理器注册通道
        SpringUtils.getBean(TcpServerManager.class).registTcpChannel(ctx.channel());
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward
     * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
     *
     * Sub-classes may override this method to change behavior.
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelInactive();

        //从管理器中释放通道资源
        SpringUtils.getBean(TcpServerManager.class).unRegistTcpChannel(ctx.channel());
    }
}
